package p29_ControllerAdvice之ResponseBodyAdvice;

import cn.hutool.core.collection.ListUtil;
import org.springframework.core.MethodParameter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor;
import p21_参数解析器.Person;
import p27_返回值处理器.MyController;

import java.io.IOException;

/**
 * 响应增强
 * 在消息转换器将java对象序列化为字符串写入响应体之前，有一处增强ResponseBodyAdvice
 * 本章学到了什么：
 *    1.@ControllerAdvice类除了前面说到的三个全局注解增强(异常、模型数据和类型转换)，还可以通过实现ResponseBodyAdvice在写入响应体之前增强
 *    2.同理，还有RequestBodyAdvice,在读取请求体内容前后有增强
 * 同前面的一样，如果是@ControllerAdvice类实现这两个接口是全局增强，如果是控制器类实现了则是当前控制器的增强
 */
public class _1_ResponseBodyAdvice {
    public static void main(String[] args) throws NoSuchMethodException, HttpMediaTypeNotAcceptableException, IOException {
        /**
         * 在启动时，会扫描到@ControllerAdvice中ResponseBodyAdvice的实现类，在创建消息转换器时，就将该实现类赋值给消息转换器
         * 后面消息转换器在写入前，就会执行增强
         */
        RequestResponseBodyMethodProcessor processor = new RequestResponseBodyMethodProcessor(
                ListUtil.of(new MappingJackson2HttpMessageConverter(), new MappingJackson2XmlHttpMessageConverter()),
                ListUtil.of(new WebConfig.MyControllerAdvice())
        );

        MockHttpServletRequest request = new MockHttpServletRequest();
        MockHttpServletResponse response = new MockHttpServletResponse();
        ServletWebRequest webRequest = new ServletWebRequest(request, response);
        processor.handleReturnValue(
                new Person("张三", 33),   //要解析的对象
                new MethodParameter(MyController.class.getMethod("test7"), -1), //控制器方法的返回值
                new ModelAndViewContainer(),
                webRequest
        );
        System.out.println(new String(response.getContentAsByteArray()));
    }
}


